namespace MTOM_Library
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Threading;

    public class FileTransferDownload : FileTransferBase
    {
        public string LocalSaveFolder;
        public string RemoteFileName;

        protected override void OnDoWork(DoWorkEventArgs e)
        {
            base.OnDoWork(e);
            base.Offset = long.Parse(e.Argument.ToString());
            int num = 0;
            base.LocalFilePath = this.LocalSaveFolder.TrimEnd(new char[] { '\\' }) + @"\" + this.RemoteFileName;
            if ((base.Offset == 0L) && File.Exists(base.LocalFilePath))
            {
                File.Create(base.LocalFilePath).Close();
            }
            long fileSize = base.WebService.GetFileSize(this.RemoteFileName);
            string str = FileTransferBase.CalcFileSize(fileSize);
            using (FileStream stream = new FileStream(base.LocalFilePath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                stream.Seek(base.Offset, SeekOrigin.Begin);
                while ((base.Offset < fileSize) && !base.CancellationPending)
                {
                    if (base.AutoSetChunkSize)
                    {
                        switch ((num % base.ChunkSizeSampleInterval))
                        {
                            case 0:
                                base.StartTime = DateTime.Now;
                                break;

                            case 1:
                                base.CalcAndSetChunkSize();
                                break;
                        }
                    }
                    try
                    {
                        byte[] buffer = base.WebService.DownloadChunk(this.RemoteFileName, base.Offset, base.ChunkSize);
                        stream.Write(buffer, 0, buffer.Length);
                        base.Offset += buffer.Length;
                    }
                    catch (Exception exception)
                    {
                        Debug.WriteLine("Exception: " + exception.ToString());
                        if (base.NumRetries++ >= base.MaxRetries)
                        {
                            stream.Close();
                            throw new Exception("Error occurred during upload, too many retries.\r\n" + exception.Message);
                        }
                    }
                    string userState = $"Transferred {FileTransferBase.CalcFileSize(base.Offset)} / {str}";
                    base.ReportProgress((int) ((base.Offset / fileSize) * 100M), userState);
                    num++;
                }
            }
            if (base.IncludeHashVerification)
            {
                base.ReportProgress(0x63, "Checking file hash...");
                if (base.ws.Url.ToLower().Contains("localhost"))
                {
                    base.CheckLocalFileHash();
                    base.RemoteFileHash = base.WebService.CheckFileHash(this.RemoteFileName);
                }
                else
                {
                    base.HashThread = new Thread(new ThreadStart(this.CheckLocalFileHash));
                    base.HashThread.Start();
                    base.WebService.Timeout = 0x927c0;
                    base.RemoteFileHash = base.WebService.CheckFileHash(this.RemoteFileName);
                    base.WebService.Timeout = 0x7530;
                    base.HashThread.Join();
                }
                if (base.LocalFileHash == base.RemoteFileHash)
                {
                    e.Result = string.Format("Hashes match exactly\r\nLocal hash:  {0}\r\nServer hash: {1}", base.LocalFileHash, base.RemoteFileHash);
                }
                else
                {
                    e.Result = string.Format("Hashes are different!\r\nLocal hash:  {0}\r\nServer hash: {1}", base.LocalFileHash, base.RemoteFileHash);
                }
            }
        }

        public void RunWorkerSync(DoWorkEventArgs e)
        {
            this.OnDoWork(e);
            base.OnRunWorkerCompleted(new RunWorkerCompletedEventArgs(e.Result, null, false));
        }
    }
}

